#define _CRT_NON_CONFORMING_SWPRINTFS
#include "libutilsconfig.h"
#include "texceptionex.h"
#if defined(_WINDOWS)
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#endif


LIB_NS_BEGIN

TSourceLine::TSourceLine(const tstring &fileName,int32 lineNumber )
	:m_fileName( fileName ),m_lineNumber( lineNumber )
{
}

TSourceLine::~TSourceLine()
{
}

tstring TSourceLine::FileName() const
{
	return m_fileName;
}

tstring TSourceLine::SzLineNumber() const
{
	TCHAR buff[8];
	_stprintf(buff,_T("%d"),m_lineNumber);
	return buff;
}

int32 TSourceLine::LineNumber() const
{
	return m_lineNumber;
}

TSourceLine& TSourceLine::operator=( const TSourceLine& right )
{
	this->m_fileName = right.m_fileName;
	this->m_lineNumber = right.m_lineNumber;
	return *this;
}

bool TSourceLine::operator==( const TSourceLine &other ) const
{
	return m_fileName == other.m_fileName  && 
		m_lineNumber == other.m_lineNumber;
}

bool TSourceLine::operator!=( const TSourceLine &other ) const
{
	return !( *this == other );
}

TMessage::TMessage()
{
}

TMessage::TMessage( const TCHAR* shortDescription ) 
	: m_shortDescription( shortDescription )
{
}

TMessage::TMessage( const tstring &shortDescription,const tstring &detail1 ) 
	: m_shortDescription( shortDescription )
{
	AddDetail( detail1 );
}

TMessage::TMessage( const TMessage& right )
{
	m_shortDescription = right.m_shortDescription;
	m_details = right.m_details;
}

const tstring & TMessage::ShortDescription() const
{
	return m_shortDescription;
}

int TMessage::DetailCount() const
{
	return m_details.size();
}

tstring TMessage::DetailAt( int index ) const
{
	if ( index < 0  ||  index >= DetailCount() )
		throw std::invalid_argument( "TMessage::detailAt() : invalid index" );

	return m_details[index];
}

tstring TMessage::Details() const
{
	tstring str;

	for (details::const_iterator it = m_details.begin(); 
		it != m_details.end(); ++it )
	{
		str += _T("- ");
		str += *it;
		str += _T('\n');
	}

	return str;
}

void TMessage::ClearDetails()
{
	m_details.clear();
}

void TMessage::AddDetail( const tstring &detail )
{
	m_details.push_back( detail );
}

void TMessage::AddDetail( const TMessage &message )
{
	m_details.insert( m_details.end(), message.m_details.begin(),
		message.m_details.end() );
}

void TMessage::SetShortDescription( const tstring &shortDescription )
{
	m_shortDescription = shortDescription;
}

bool TMessage::operator!=( const TMessage &other ) const
{
	return !( *this == other );
}

bool TMessage::operator==( const TMessage &other ) const
{
	return m_shortDescription == other.m_shortDescription  && 
		m_details == other.m_details;
}

TException::TException( const TCHAR* szMessage ,const TSourceLine &sourceLine) 
	: m_message( szMessage ), m_sourceLine( sourceLine )
{
}

TException::TException( const TMessage &message , 
	const TSourceLine &sourceLine) : m_message( message )
	, m_sourceLine( sourceLine )
{
}

TException::TException(tstring message,tstring fileName,int32 lineNumber) 
	: m_message( message.c_str() ), m_sourceLine( fileName, lineNumber )
{
}

TException::TException( const TException &other ) 
	: std::exception( other ),m_sourceLine(other.m_sourceLine)
{
	m_message = other.m_message;
}

void TException::Show()
{
	tstring info;
	info = m_sourceLine.FileName() + _T("[line") + m_sourceLine.SzLineNumber() + 		_T("]\n") ;//+ what();

#ifdef WIN32
	::MessageBox(NULL,info.c_str(),_T("Eception Throw"),MB_OK);
#else
	printf("Exception Throw:%s",info.c_str());
#endif
}

TException::~TException() throw()
{
}

TException & TException::operator=( const TException &other )
{
	if ( &other != this )
	{
		m_message = other.m_message;
		m_sourceLine = other.m_sourceLine;
	}

	return *this;
}

TSourceLine TException::SourceLine() const
{
	return m_sourceLine;
}

const TCHAR * TException::What() const throw()
{
	//TException *mutableThis = const_cast<TException*> (this) ;
	tstring whatMessage = m_message.ShortDescription() + _T("\n") +
		m_message.Details();
	return whatMessage.c_str();
}

TMessage TException::Message() const
{
	return m_message;
}

void TException::SetMessage( const TMessage &message )
{
	m_message = message;
}

tstring TException::FileName() const
{
	return m_sourceLine.FileName();
}

TException * TException::Clone() const
{
	return new TException( *this );
}

int32 TException::LineNumber() const
{
	return m_sourceLine.LineNumber();
}

TAutoTException& TAutoTException::operator=( bool right )
{
	if (!right)
	{
		throw TException(_T("bool assert as false "),m_fileName,m_lineNumber);
	}

	return *this;
}

TAutoTException& TAutoTException::operator=( int32 val )
{
	if (!val)
	{
		throw TException(_T("int assert as 0"),m_fileName,m_lineNumber);
	}

	return *this;
}

TAutoTException& TAutoTException::operator=(void* pval )
{
	if (pval==NULL)
	{
		throw TException(_T("point assert as NULL"),m_fileName,m_lineNumber);
	}

	return *this;
}

TAutoTException& TAutoTException::operator()( const TCHAR* szFileName,
	int32 lineNumber)
{
	m_fileName = szFileName;
	m_lineNumber = lineNumber;
	return *this;
}

TAutoTException::TAutoTException()
{
}

TAutoTException::~TAutoTException()
{
}

LIB_NS_END